package com.ecarx.vhaltests.hy11.testcases.system.windowdoorlock;
import static android.car.VehiclePropertyIds.WINDOW_POS;
import static org.junit.Assert.assertEquals;

import android.car.VehicleAreaWindow;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.property.CarPropertyManager;
import android.util.Log;

import com.ecarx.vhaltests.IpcpClient;
import com.ecarx.vhaltests.VehicleConstants;
import com.ecarx.vhaltests.VhalUnitTestBase;
import com.ecarx.xui.adaptapi.car.IWrapper;

import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class VehicleWindowPosTest extends VhalUnitTestBase {
    protected static IWrapper wrapper;
    private static IpcpClient ipcpClient = new IpcpClient();
    private static final int row1Left = VehicleAreaWindow.WINDOW_ROW_1_LEFT;
    private static final int row1Right = VehicleAreaWindow.WINDOW_ROW_1_RIGHT;
    private static final int row2Left = VehicleAreaWindow.WINDOW_ROW_2_LEFT;
    private static final int row2Right = VehicleAreaWindow.WINDOW_ROW_2_RIGHT;
    private static int l1cbkPropValue;
    private static int l1cbkPropStatus;
    private static int r1cbkPropValue;
    private static int r1cbkPropStatus;
    private static int l2cbkPropValue;
    private static int l2cbkPropStatus;
    private static int r2cbkPropValue;
    private static int r2cbkPropStatus;
    private static int cbkPropValue;
    private static int cbkPropStatus;
    final static Object lock = new Object();
    final static Object lock2 = new Object();
    final static Object lock3 = new Object();

    final static Object lock4 = new Object();

    @BeforeClass
    public static void testInit() {
        mCarPropertyMgr.registerCallback(carPropertyEventCallback, WINDOW_POS, CarPropertyManager.SENSOR_RATE_ONCHANGE);
        setConfig();
    }

    public boolean availability(int area){
        return mCarPropertyMgr.isPropertyAvailable(WINDOW_POS, area);
    }

    public static void setConfig(){
        int ccSvcId = 135;
        int[] ccOperIds = {200};
        boolean ccSet = ipcpClient.setConfig(ccSvcId, ccOperIds);
        assertEquals(true, ccSet);

        int cemSvcId = 37;
        int[] cemOperId = {999};
        boolean cemResult = ipcpClient.setConfig(cemSvcId, cemOperId);
        assertEquals(true, cemResult);
        delay();
    }

    public void setCarConfig(boolean isAvail){
        int ccSvcId = 135;
        int ccOperIds = 200;
        int[] configs = {8, 2};
        int[] values = {1, isAvail? 2:3};
        boolean ccResult = ipcpClient.setCarconfigSignal(ccSvcId, ccOperIds, configs, values);
        delay();
        assertEquals(true, ccResult);
        Log.d("vli", "setCarConfig pass");
    }

    public void setCem(boolean isActive){
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1UsgModSts","vehModMngtGlbSafe1CarModSts1"};
        int[] cemValues = {isActive? VehicleConstants.USG_MODE_CONVENIENCE:VehicleConstants.USG_MODE_ABANDON,
                VehicleConstants.CAR_MODE_DYNO};
        boolean cemUsgResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        delay();
        assertEquals(true, cemUsgResult);
        Log.d("vli", "setCem pass");
    }

    public void mockMcuSignal(int winPosnStsAtDrvr, int winPosnStsAtPass, int winPosnStsAtReLe, int winPosnStsAtReRi){
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1UsgModSts","vehModMngtGlbSafe1CarModSts1","winPosnStsAtDrvr","winPosnStsAtPass","winPosnStsAtReLe","winPosnStsAtReRi"};
        int[] cemValues = {VehicleConstants.USG_MODE_CONVENIENCE, VehicleConstants.CAR_MODE_DYNO, winPosnStsAtDrvr, winPosnStsAtPass, winPosnStsAtReLe, winPosnStsAtReRi};
        boolean cemUsgResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        delay();
        assertEquals(true, cemUsgResult);
    }

    @Test
    public void test_001Row1Active(){
        setCem(true);
        int l1 = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left).getStatus();
        int r1 = mCarPropertyMgr.getProperty(WINDOW_POS, row1Right).getStatus();
        assertEquals(0, l1);
        assertEquals(0, r1);
    }

    @Test
    public void test_002Row1NotActive(){
        setCem(false);
        int l1 = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left).getStatus();
        int r1 = mCarPropertyMgr.getProperty(WINDOW_POS, row1Right).getStatus();
        assertEquals(1, l1);
        assertEquals(1, r1);
    }

    @Test
    public void test_003Row2Active(){
        setCarConfig(true);
        setCem(true);
        int l2 = mCarPropertyMgr.getProperty(WINDOW_POS, row2Left).getStatus();
        int r2 = mCarPropertyMgr.getProperty(WINDOW_POS, row2Right).getStatus();
        assertEquals(0, l2);
        assertEquals(0, r2);
    }

    @Test
    public void test_004Row2NotActive(){
        setCarConfig(true);
        setCem(false);
        int l2 = mCarPropertyMgr.getProperty(WINDOW_POS, row2Left).getStatus();
        int r2 = mCarPropertyMgr.getProperty(WINDOW_POS, row2Right).getStatus();
        assertEquals(1, l2);
        assertEquals(1, r2);
    }

    @Test
    public void test_005Row2NotAvail(){
        setCarConfig(false);
        assertEquals(false, availability(row2Left));
        assertEquals(false, availability(row2Right));
    }

    @Test
    public void test_006Row1AndRow2Active(){
        setCarConfig(false);
        setCem(true);
        int res = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right).getStatus();
        assertEquals(0, res);
    }

    @Test
    public void test_007Row1AndRow2NotActive(){
        setCarConfig(false);
        setCem(false);
        int res = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right).getStatus();
        assertEquals(1, res);
    }

    @Test
    public void test_008SetAndGetNormalVal(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mockMcuSignal(1,2,3,4);
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row1Left, 0);
        assertEquals(0, l1cbkPropValue);
        delay();
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row1Right, 4);
        assertEquals(4, r1cbkPropValue);
        delay();
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row2Left, 8);
        assertEquals(8, l2cbkPropValue);
        delay();
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row2Right,12);
        assertEquals(12, r2cbkPropValue);
        delay();
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right, 16);

    }

    @Test
    public void test_009MockNormalVal(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mockMcuSignal(2, 3,4,5);
        delay();
        assertEquals(4, l1cbkPropValue);
        assertEquals(8, r1cbkPropValue);
        assertEquals(12, l2cbkPropValue);
        assertEquals(16, r2cbkPropValue);
    }

    @Test
    public void test_011SetAbnormalVal(){
        setCarConfig(false);
        setCarConfig(true);
        setCem(true);
        mockMcuSignal(4,5, 2, 7);
        mCarPropertyMgr.setIntProperty(WINDOW_POS,row1Left, 13);
        mCarPropertyMgr.setIntProperty(WINDOW_POS,row1Right, 15);
        mCarPropertyMgr.setIntProperty(WINDOW_POS,row2Left,3);
        mCarPropertyMgr.setIntProperty(WINDOW_POS,row2Right,25);
        delay();
        assertEquals(12, l1cbkPropValue);
        assertEquals(16, r1cbkPropValue);
        assertEquals(4, l2cbkPropValue);
        assertEquals(24, r2cbkPropValue);
    }

    @Test
    public void test_012SetAllArea(){
        setCarConfig(false);
        setCem(true);
        mockMcuSignal(26,26,5,5);
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right, 100);
        assertEquals(100, l1cbkPropValue);
        assertEquals(100, r1cbkPropValue);
        delay();
        setCarConfig(true);
        mCarPropertyMgr.setIntProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right, 3);
        assertEquals(16, l2cbkPropValue);
        assertEquals(16,r2cbkPropValue);
    }

    public void setUsgModInactive(){
        int cemSvcId = 37;
        int cemOperId = 999;
        String[] cems = {"vehModMngtGlbSafe1UsgModSts","vehModMngtGlbSafe1CarModSts1"};
        int[] cemValues = {VehicleConstants.USG_MODE_INACTIVE, VehicleConstants.CAR_MODE_DYNO};
        boolean cemUsgResult = ipcpClient.setCEMSignal(cemSvcId, cemOperId, cems, cemValues);
        delay();
        assertEquals(true, cemUsgResult);
        Log.d("vli", "setCem pass");
    }

    @Test
    public void test_013UsgModChangeInactive(){
        setCarConfig(true);
        setCem(true);
        assertEquals(0, l1cbkPropStatus);
        assertEquals(0, r1cbkPropStatus);
        assertEquals(0, l2cbkPropStatus);
        assertEquals(0, r2cbkPropStatus);
        setUsgModInactive();
        delay(2000);
        assertEquals(0, l1cbkPropStatus);
        assertEquals(0, r1cbkPropStatus);
        assertEquals(0, l2cbkPropStatus);
        assertEquals(0, r2cbkPropStatus);
        delay(121 * 1000);
        assertEquals(1, l1cbkPropStatus);
        assertEquals(1, r1cbkPropStatus);
        assertEquals(1, l2cbkPropStatus);
        assertEquals(1, r2cbkPropStatus);
    }

    @Test
    public void test_014AllAreaUsgModChangeInactive(){
        setCem(true);
        int sts = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right).getStatus();
        assertEquals(0, sts);
        setUsgModInactive();
        delay(2000);
        sts = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right).getStatus();
        assertEquals(0, sts);
        delay(121 * 1000);
        sts = mCarPropertyMgr.getProperty(WINDOW_POS, row1Left|row1Right|row2Left|row2Right).getStatus();
        assertEquals(1, sts);
    }

    private static CarPropertyManager.CarPropertyEventCallback carPropertyEventCallback = new CarPropertyManager.CarPropertyEventCallback() {
        @Override
        public void onChangeEvent(CarPropertyValue carPropertyValue) {
            if(carPropertyValue.getAreaId() == row1Left) {
                try {
                    l1cbkPropValue = (int) carPropertyValue.getValue();
                    l1cbkPropStatus = carPropertyValue.getStatus();
                    synchronized (lock) {
                        lock.notify();
                    }

                } catch (Exception e) {
                    Log.e("vli", e.getMessage());
                }
            } else if (carPropertyValue.getAreaId() == row1Right) {
                try {
                    r1cbkPropValue = (int) carPropertyValue.getValue();
                    r1cbkPropStatus = carPropertyValue.getStatus();
                    synchronized (lock2) {
                        lock2.notify();
                    }
                } catch (Exception e) {
                    Log.e("vli", e.getMessage());
                }
            } else if (carPropertyValue.getAreaId() == row2Left) {
                try {
                    l2cbkPropValue = (int) carPropertyValue.getValue();
                    l2cbkPropStatus = carPropertyValue.getStatus();
                    synchronized (lock3) {
                        lock3.notify();
                    }

                } catch (Exception e) {
                    Log.e("vli", e.getMessage());
                }
            } else if (carPropertyValue.getAreaId() == row2Right) {
                try {
                    r2cbkPropValue = (int) carPropertyValue.getValue();
                    r2cbkPropStatus = carPropertyValue.getStatus();
                    synchronized (lock4) {
                        lock4.notify();
                    }

                } catch (Exception e) {
                    Log.e("vli", e.getMessage());
                }
            } else {
                try {
                    cbkPropValue = (int) carPropertyValue.getValue();
                    cbkPropStatus = carPropertyValue.getStatus();
                    synchronized (lock) {
                        lock.notify();
                    }

                } catch (Exception e) {
                    Log.e("vli", e.getMessage());
                }
            }
        }

        @Override
        public void onErrorEvent(int i, int i1) {

        }
    };
}